#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import shutil
import hashlib

def get_file_hash(file_path, algorithm="md5"):
    """获取文件哈希值"""
    if algorithm.lower() == "md5":
        hash_func = hashlib.md5()
    elif algorithm.lower() == "sha1":
        hash_func = hashlib.sha1()
    elif algorithm.lower() == "sha256":
        hash_func = hashlib.sha256()
    else:
        raise ValueError(f"不支持的哈希算法: {algorithm}")
    
    with open(file_path, "rb") as f:
        for chunk in iter(lambda: f.read(4096), b""):
            hash_func.update(chunk)
    
    return hash_func.hexdigest()

def is_file_changed(file_path1, file_path2):
    """比较两个文件是否不同"""
    if not os.path.exists(file_path2):
        return True
    
    # 比较文件大小
    size1 = os.path.getsize(file_path1)
    size2 = os.path.getsize(file_path2)
    
    if size1 != size2:
        return True
    
    # 比较文件哈希值
    try:
        hash1 = get_file_hash(file_path1)
        hash2 = get_file_hash(file_path2)
        return hash1 != hash2
    except:
        # 如果计算哈希失败，则认为文件已更改
        return True

def safe_copy(src, dst, overwrite=True):
    """安全复制文件"""
    # 确保目标目录存在
    os.makedirs(os.path.dirname(dst), exist_ok=True)
    
    # 如果文件已存在且不允许覆盖，则跳过
    if not overwrite and os.path.exists(dst):
        return False
    
    try:
        shutil.copy2(src, dst)
        return True
    except Exception as e:
        print(f"复制文件失败: {e}")
        return False

def should_exclude_file(file_path, exclude_patterns):
    """检查文件是否应该被排除"""
    file_name = os.path.basename(file_path)
    
    for pattern in exclude_patterns:
        if not pattern:
            continue
        
        # 处理通配符
        if '*' in pattern or '?' in pattern:
            import fnmatch
            if fnmatch.fnmatch(file_name, pattern):
                return True
        else:
            # 简单字符串匹配
            if pattern == file_name:
                return True
    
    return False

def get_directory_size(directory):
    """获取目录大小"""
    total_size = 0
    try:
        for dirpath, dirnames, filenames in os.walk(directory):
            for filename in filenames:
                file_path = os.path.join(dirpath, filename)
                if os.path.exists(file_path):
                    total_size += os.path.getsize(file_path)
    except Exception as e:
        print(f"计算目录大小失败: {e}")
    
    return total_size

def format_file_size(size_bytes):
    """格式化文件大小"""
    if size_bytes < 1024:
        return f"{size_bytes} B"
    elif size_bytes < 1024 * 1024:
        return f"{size_bytes / 1024:.2f} KB"
    elif size_bytes < 1024 * 1024 * 1024:
        return f"{size_bytes / (1024 * 1024):.2f} MB"
    else:
        return f"{size_bytes / (1024 * 1024 * 1024):.2f} GB"